home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / overview / dts.utilities / utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  47.4 KB  |  1,699 lines

  1. /*
  2.     File:        Utilities.c
  3.  
  4.     Contains:    Collection of Utilities for DTS Sample code
  5.  
  6.     Written by:     
  7.  
  8.     Copyright:    Copyright © 1988-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 8/18/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24. #ifndef __CONTROLS__
  25. #include <Controls.h>
  26. #endif
  27.  
  28. #ifndef __DEVICES__
  29. #include <Devices.h>
  30. #endif
  31.  
  32. #ifndef __EVENTS__
  33. #include <Events.h>
  34. #endif
  35.  
  36. #ifndef __FIXMATH__
  37. #include <FixMath.h>
  38. #endif
  39.  
  40. #ifndef __FONTS__
  41. #include <Fonts.h>
  42. #endif
  43.  
  44. #ifndef __MENUS__
  45. #include <Menus.h>
  46. #endif
  47.  
  48. #ifndef __PACKAGES__
  49. #include <Packages.h>
  50. #endif
  51.  
  52. #ifndef __RESOURCES__
  53. #include <Resources.h>
  54. #endif
  55.  
  56. #ifndef __SCRIPT__
  57. #include <Script.h>
  58. #endif
  59.  
  60. #ifndef __SEGLOAD__
  61. #include <SegLoad.h>
  62. #endif
  63.  
  64. #ifndef __STRING__
  65. #include <String.h>
  66. #endif
  67.  
  68. #ifndef __LOWMEM__
  69. #include <LowMem.h>
  70. #endif
  71.  
  72. #ifndef __TEXTEDIT__
  73. #include <TextEdit.h>
  74. #endif
  75.  
  76. #ifndef __TOOLUTILS__
  77. #include <ToolUtils.h>
  78. #endif
  79.  
  80. #ifndef __TRAPS__
  81. #include <Traps.h>
  82. #endif
  83.  
  84. #ifndef __ERRORS__
  85. #include <Errors.h>
  86. #endif
  87.  
  88. #include "Utilities.h"
  89. #include <TextUtils.h>
  90. /*-----------------------------------------------------------------------------------------
  91.     Private Functions 
  92. -----------------------------------------------------------------------------------------*/
  93.  
  94.  
  95.  
  96. /*-----------------------------------------------------------------------------------------
  97.     Global variables -- See Utilities.h for more explanation
  98. -----------------------------------------------------------------------------------------*/
  99. short            gMachineType;            /* which machine this is */
  100. short            gSystemVersion;            /* System version number */
  101. short            gProcessorType;            /* which CPU this is */
  102. Boolean            gHasFPU;                /* true if machine has an FPU */
  103. short            gQDVersion;                /* major QD version #; 0 for original, 
  104.                                                     1 for color QD, 2 for 32-bit QD */
  105. short            gKeyboardType;            /* which type of keyboard is present */
  106. short            gAppleTalkVersion;        /* AppleTalk version number */
  107. Boolean            gHasPMMU;                /* true if machine has a PMMU or equivalent */
  108. short            gAUXVersion;            /* major A/UX version number (0 if not present) */
  109.  
  110. Boolean            gHasWaitNextEvent;
  111. short            gAppResRef;
  112. Boolean            gInBackground;
  113. Str255            gAppName;
  114. OSType            gSignature = '????';
  115. Boolean            gUtilitiesInited;
  116.  
  117.  
  118.  
  119.  
  120. /*****************************************************************************/
  121.  
  122.  
  123.  
  124. /* Given an alert ID and a window pointer the alert relates to, this function
  125. ** will center the alert’s rectangle before showing it on the proper screen.
  126. ** This follows the Apple Human Interface Guidelines for where to place a
  127. ** centered window on the screen.  If the alert is not closely associated with
  128. ** another window, pass a NULL for the window pointer of the related window.  If
  129. ** you pass a NULL, the alert is simply displayed where the resource
  130. ** would indicate.  Note that if an error occurs when getting the resource for
  131. ** the alert, then the alert is not displayed, and the returned value is not
  132. ** the item hit, but is the error that occured when reading the resource. */
  133.  
  134. #pragma segment UtilMain
  135. short    CenteredAlert(short alertID, WindowPtr relatedWindow)
  136. {
  137.     AlertTHndl    alertHandle;
  138.     WindowPtr    tempWindow;
  139.     Rect        alertRect;
  140.     short        itemHit;
  141.     char        hstate;
  142.     OSErr        err;
  143.     
  144.     alertHandle = (AlertTHndl)GetAppResource('ALRT', alertID, &err);
  145.     if (err) return((short)err);
  146.  
  147.     hstate = LockHandleHigh((Handle)alertHandle);
  148.         /* Do our part to help prevent fragmentation. */
  149.  
  150.     alertRect = (*alertHandle)->boundsRect;
  151.         /* Preserve the real alert bounding rectangle. */
  152.  
  153.     if (tempWindow = NewWindow(NULL, &alertRect, "\p", false, dBoxProc,
  154.                               (WindowPtr)NULL, false, 0)) {
  155.         /* Use an invisible temporary window to calculate where the alert will go. */
  156.  
  157.         (*alertHandle)->boundsRect = CenterWindow(tempWindow, relatedWindow);
  158.         DisposeWindow(tempWindow);
  159.     }
  160.  
  161.     itemHit = Alert(alertID, NULL);
  162.  
  163.     (*alertHandle)->boundsRect = alertRect;
  164.         /* Restore the resource's bounding rect, so if this resource is ever used
  165.         ** not through this function, it will open where the resource indicates. */
  166.  
  167.     HSetState((Handle)alertHandle, hstate);
  168.     return(itemHit);
  169. }
  170.  
  171.  
  172.  
  173. /*****************************************************************************/
  174.  
  175.  
  176.  
  177. /* Given two rects, this function centers the second one within the first. */
  178.  
  179. #pragma segment UtilMain
  180. void    CenterRectInRect(Rect outerRect, Rect *innerRect)
  181. {
  182.     PositionRectInRect(outerRect, innerRect, FixRatio(1, 2), FixRatio(1, 2));
  183. }
  184.  
  185.  
  186.  
  187. /*****************************************************************************/
  188.  
  189.  
  190.  
  191. /* Center a window within a particular device.  The device to center the window
  192. ** within is determined by passing a related window.  This allows related
  193. ** windows to be kept on the same device.  This is useful if an alert related
  194. ** to a specific window, for example. */
  195.  
  196. #pragma segment UtilMain
  197. Rect    CenterWindow(WindowPtr window, WindowPtr relatedWindow)
  198. {
  199.     WindowPtr    whichDevice;
  200.     Rect        deviceRect, oldWindowRect, newWindowRect, contentRect;
  201.  
  202.     if (!(whichDevice = relatedWindow)) whichDevice = window;
  203.         /* If we have a window to center against, use the device for that window,
  204.         ** else use the device for the window that is getting centered. */
  205.  
  206.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  207.         /* We now have the rectangle of the device we want to center within. */
  208.  
  209.     oldWindowRect = newWindowRect = GetWindowStructureRect(window);
  210.  
  211.     PositionRectInRect(deviceRect, &newWindowRect, FixRatio (1, 2),
  212.                        FixRatio (1, 3));
  213.         /* Figure out the new window strucRect so we can compare it against
  214.         ** the old strucRect.  This will tell us how much to move the window. */
  215.  
  216.     contentRect = GetWindowContentRect(window);
  217.         /* Get where the window is now. */
  218.  
  219.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  220.                             newWindowRect.top  - oldWindowRect.top);
  221.         /* Calculate the new content rect. */
  222.  
  223.     MoveWindow(window, contentRect.left, contentRect.top, false);
  224.         /* Move the window to the new location. */
  225.  
  226.     return(contentRect);
  227. }
  228.  
  229.  
  230.  
  231. /*****************************************************************************/
  232.  
  233.  
  234.  
  235. /* Close a window.  This handles desk accessory and application windows.  Use
  236. ** this call (instead of DisposeAnyWindow) if the memory for the window was
  237. ** allocated by you.  (Same as CloseWindow v.s. DisposeWindow.) */
  238.  
  239. #pragma segment UtilMain
  240. void    CloseAnyWindow(WindowPtr window)
  241. {
  242.     if (IsDAWindow(window))
  243.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  244.     else {
  245.         if (IsAppWindow(window))
  246.             CloseWindow(window);
  247.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  248.             CloseDialog((DialogPtr)window);
  249.     }
  250. }
  251.  
  252.  
  253.  
  254. /*****************************************************************************/
  255.  
  256.  
  257.  
  258. /* Dispose a window.  This handles desk accessory and application windows.  Use
  259. ** this call (instead of CloseAnyWindow) if you want the memory for the window
  260. ** record to be disposed of.  (Same as CloseWindow v.s. DisposeWindow.) */
  261.  
  262. #pragma segment UtilMain
  263. void    DisposeAnyWindow(WindowPtr window)
  264. {
  265.     if (IsDAWindow(window))
  266.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  267.     else {
  268.         if (IsAppWindow(window))
  269.             DisposeWindow(window);
  270.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  271.             DisposeDialog((DialogPtr)window);
  272.     }
  273. }
  274.  
  275.  
  276.  
  277. /*****************************************************************************/
  278.  
  279.  
  280.  
  281. /* Display an alert that tells the user an error occurred, then exit the
  282. ** program.  This function is used as an ultimate bail-out for serious errors
  283. ** that prohibit the continuation of the application.  Errors that do not
  284. ** require the termination of the application should be handled in a different
  285. ** manner. */  
  286.  
  287. #pragma segment UtilMain
  288. void    DeathAlert(short errResID, short errStringIndex)
  289. {
  290.     ErrorAlert(errResID, errStringIndex);
  291.     ExitToShell();
  292. }
  293.  
  294.  
  295.  
  296. /*****************************************************************************/
  297.  
  298.  
  299.  
  300. /* Display an alert that tells the user an error occurred, then exit the
  301. ** program.  This function is used as an ultimate bail-out for serious errors
  302. ** that prohibit the continuation of the application.  Errors that do not
  303. ** require the termination of the application should be handled in a different
  304. ** manner.  The message parameter is an error code that is to be displayed. */
  305.  
  306. #pragma segment UtilMain
  307. void    DeathAlertMessage(short errResID, short errStringIndex, short message)
  308. {
  309.     ErrorAlertMessage(errResID, errStringIndex, message);
  310.     ExitToShell();
  311. }
  312.  
  313.  
  314.  
  315. /*****************************************************************************/
  316.  
  317.  
  318.  
  319. /* Display an alert that tells the user an error occurred. */
  320.  
  321. #pragma segment UtilMain
  322. void    ErrorAlert(short errResID, short errStringIndex)
  323. {
  324.     ErrorAlertMessage(errResID, errStringIndex, 0);
  325. }
  326.  
  327.  
  328.  
  329. /*****************************************************************************/
  330.  
  331.  
  332.  
  333. /* Display an alert to inform the user of an error.  errStringIndex acts as an
  334. ** index into a STR# resource of error messages.  If no errStringIndex is
  335. ** given, i.e. = 0, then use a standard message.  If message is not noErr then
  336. ** display it as well.
  337. **
  338. ** BUG NOTE:  GetIndString returns a bogus String if the index is
  339. **            not positive. */
  340.   
  341. #pragma segment UtilMain
  342. void    ErrorAlertMessage(short errResID, short errStringIndex, short message)
  343. {
  344.     Str255    msg1, msg2;
  345.  
  346.     SetCursor(&QD(arrow));
  347.  
  348.     if (errStringIndex <= 0) {
  349.         errStringIndex = eStandardErr;
  350.         errResID = rUtilStrings;
  351.     }
  352.     GetIndString(msg1, errResID, errStringIndex);
  353.  
  354.     if (message == noErr) {
  355.         ParamText(msg1, "\p", "\p", "\p");
  356.         CenteredAlert(rUtilErrorAlert, NULL);
  357.     } else {
  358.         NumToString(message, msg2);
  359.         ParamText(msg1, msg2, "\p", "\p");
  360.         CenteredAlert(rUtilErrorMessageAlert, NULL);
  361.     }
  362. }
  363.  
  364.  
  365.  
  366. /*****************************************************************************/
  367.  
  368.  
  369.  
  370. /* FindSysFolder returns the (real) vRefNum, and the DirID of the current
  371. ** system folder.  It uses the Folder Manager if present, otherwise it falls
  372. ** back to SysEnvirons.  It returns zero on success, otherwise a standard
  373. ** system error. */
  374.  
  375. #pragma segment UtilMain
  376. OSErr    FindSysFolder(short *foundVRefNum, long *foundDirID)
  377. {
  378.     long            gesResponse;
  379.     SysEnvRec        envRec;
  380.     WDPBRec            myWDPB;
  381.     unsigned char    volName[34];
  382.     OSErr            err;
  383.     
  384.     
  385.     *foundVRefNum = 0;
  386.     *foundDirID = 0;
  387.     if (!Gestalt (gestaltFindFolderAttr, &gesResponse) &&
  388.         BTstQ (gesResponse, gestaltFindFolderPresent)) {    /* Does Folder Manager exist? */
  389.             err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder, 
  390.                 foundVRefNum, foundDirID);
  391.     } else {
  392.         /* Gestalt can't give us the answer, so we resort to SysEnvirons */
  393.         if (!(err = SysEnvirons (curSysEnvVers, &envRec))) {
  394.             myWDPB.ioVRefNum = envRec.sysVRefNum;
  395.             volName[0] = '\000';                    /* Zero volume name */
  396.             myWDPB.ioNamePtr = volName;
  397.             myWDPB.ioWDIndex = 0;
  398.             myWDPB.ioWDProcID = 0;
  399.             if (!(err = PBGetWDInfo (&myWDPB, 0))) {
  400.                 *foundVRefNum = myWDPB.ioWDVRefNum;
  401.                 *foundDirID = myWDPB.ioWDDirID;
  402.             }
  403.         }
  404.     }
  405.     return (err);
  406. }
  407.  
  408.  
  409.  
  410. /*****************************************************************************/
  411.  
  412.  
  413.  
  414. /* GetAppIndResource gets a resource from the application's resource file
  415. ** by index. */
  416.  
  417. #pragma segment UtilMain
  418. Handle    GetAppIndResource(ResType theType, short index, OSErr *err)
  419. {
  420. #pragma unused (err)
  421.  
  422.     short    savedResFile;
  423.     Handle    returnHandle;
  424.     
  425.     savedResFile = CurResFile ();
  426.     UseResFile (gAppResRef);
  427.     returnHandle = Get1IndResource(theType, index);
  428.     UseResFile (savedResFile);
  429.     return (returnHandle);
  430. }
  431.  
  432.  
  433.  
  434. /*****************************************************************************/
  435.  
  436.  
  437.  
  438. /* GetAppNamedResource gets a resource from the application's resource file
  439. ** by name. */
  440.  
  441. #pragma segment UtilMain
  442. Handle    GetAppNamedResource(ResType theType, Str255 name, OSErr *err)
  443. {
  444.     short    savedResFile;
  445.     Handle    returnHandle;
  446.     
  447.     savedResFile = CurResFile ();
  448.     UseResFile (gAppResRef);
  449.     returnHandle = Get1NamedResource(theType, name);
  450.     *err = ResError();
  451.     UseResFile (savedResFile);
  452.     return (returnHandle);
  453. }
  454.  
  455.  
  456.  
  457. /*****************************************************************************/
  458.  
  459.  
  460.  
  461. /* GetAppResource gets a resource from the application's resource file by
  462. ** resource ID. */
  463.  
  464. #pragma segment UtilMain
  465. Handle    GetAppResource(ResType theType,short theID, OSErr *err)
  466. {
  467.     short    savedResFile;
  468.     Handle    returnHandle;
  469.     
  470.     savedResFile = CurResFile ();
  471.     UseResFile (gAppResRef);
  472.     returnHandle = Get1Resource(theType, theID);
  473.     *err = ResError();
  474.     UseResFile (savedResFile);
  475.     return (returnHandle);
  476. }
  477.  
  478.  
  479.  
  480. /*****************************************************************************/
  481.  
  482.  
  483.  
  484. /* Checks for the presence of A/UX by whatever means is appropriate.  Returns
  485. ** the major version number of A/UX (i.e. 0 if A/UX is not present, 1 for
  486. ** any 1.x.x version 2 for any 2.x version, etc.
  487. **
  488. ** This code should work for all past, present and future A/UX systems. */
  489.  
  490. #pragma segment UtilMain
  491. short    GetAUXVersion(void)
  492. {
  493.     long    auxVersion;
  494.     short    err;
  495.     
  496.         /*
  497.      *    This code assumes the Gestalt glue checks for the presence of the _Gestalt
  498.      *    trap and does something intelligent if the trap is unavailable, i.e.
  499.      *    return unknown selector.
  500.      */
  501.     auxVersion = 0;
  502.     err = Gestalt(gestaltAUXVersion, &auxVersion);
  503.     /*
  504.      *    If gestaltUnknownErr or gestaltUndefSelectorErr was returned, then either 
  505.      *    we weren't running on A/UX, or the _Gestalt trap is unavailable so use 
  506.      *    HWCfgFlags instead.
  507.      *    All other errors are ignored (implies A/UX not present).
  508.      */
  509.     if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {    /* Use HWCfgFlags */
  510.         if (BTstQ(LMGetHWCfgFlags(), 9))
  511.             auxVersion = 0x100;            /* Do Have A/UX, so assume version 1.x.x */
  512.     }
  513.     /*
  514.      *    Now right shift auxVersion by 8 bits to get major version number
  515.      */
  516.     auxVersion >>= 8;
  517.     return((short)auxVersion);
  518. }
  519.  
  520.  
  521.  
  522. /*****************************************************************************/
  523.  
  524.  
  525.  
  526. /* Given a dialog ID and a window pointer the dialog relates to, this function
  527. ** will center the dialog’s rectangle before showing it on the proper screen.
  528. ** This follows the Apple Human Interface Guidelines for where to place a
  529. ** centered window on the screen.  If the dialog is not closely associated with
  530. ** another window, pass a NULL for the window pointer of the related window.  If
  531. ** you pass a NULL, the dialog is simply displayed where the resource
  532. ** would indicate. */
  533.  
  534. #pragma segment UtilMain
  535. DialogPtr    GetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind)
  536. {
  537.     DialogTHndl        dlogResource;
  538.     DialogPtr        dialog;
  539.     Boolean            oldVis;
  540.     char            hstate;
  541.     OSErr            err;
  542.     
  543.     dialog = NULL;
  544.     if (dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err)) {
  545.         hstate = LockHandleHigh((Handle)dlogResource);
  546.         oldVis = (*dlogResource)->visible;
  547.         (*dlogResource)->visible = false;
  548.         if (dialog = GetNewDialog(id, storage, behind)) {
  549.             CenterWindow(dialog, relatedWindow);
  550.             if (oldVis) ShowWindow(dialog);
  551.         }
  552.         (*dlogResource)->visible = oldVis;
  553.         HSetState((Handle)dlogResource, hstate);
  554.     }
  555.     return(dialog);
  556. }
  557.  
  558.  
  559.  
  560. /*****************************************************************************/
  561.  
  562.  
  563.  
  564. /* Given a window ID and a window pointer the window relates to, this function
  565. ** will center the window’s rectangle before showing it on the proper screen.
  566. ** This follows the Apple Human Interface Guidelines for where to place a
  567. ** centered window on the screen.  If the window is not closely associated with
  568. ** another window, pass a NULL for the window pointer of the related window.  If
  569. ** you pass a NULL, the window is simply displayed where the resource
  570. ** would indicate. */
  571.  
  572. #pragma segment UtilMain
  573. WindowPtr    GetCenteredWindow(short id, Ptr storage, WindowPtr relatedWindow,
  574.                               WindowPtr behind, Boolean inColor)
  575. {
  576.     return(GetSomeKindOfWindow(CenterWindow, id, storage, relatedWindow, behind, inColor));
  577. }
  578.  
  579.  
  580.  
  581. /*****************************************************************************/
  582.  
  583.  
  584.  
  585. #pragma segment UtilMain
  586. Boolean GetCheckOrRadio(DialogPtr dlgPtr, short itemNo)
  587. {
  588.     short    iKind;
  589.     Handle    iHandle;
  590.     Rect    iRect;
  591.  
  592.     GetDialogItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  593.     return(GetControlValue((ControlHandle)iHandle) != 0);
  594. }
  595.  
  596.  
  597.  
  598. /*****************************************************************************/
  599.  
  600.  
  601.  
  602. /* GetGestaltResult returns the result value from Gestalt for the specified
  603. ** selector.  If Gestalt returned an error GetGestaltResult returns zero.
  604. ** Use of this function is only cool if we don't care whether Gestalt returned
  605. ** an error.  In many cases you may need to know the exact Gestalt error code
  606. ** so then this function would be inappropriate.
  607. ** See GetAUXVersion for an example. */
  608.  
  609. #pragma segment UtilMain
  610. long    GetGestaltResult(OSType gestaltSelector)
  611. {
  612.     long    gestaltResult;
  613.     
  614.     if (Gestalt(gestaltSelector, &gestaltResult) == noErr)
  615.         return(gestaltResult);
  616.     else
  617.         return(0);
  618. }
  619.  
  620.  
  621.  
  622. /*****************************************************************************/
  623.  
  624.  
  625.  
  626. /* Get the global coordinates of the mouse.  When you call OSEventAvail it will
  627. ** return either a pending event or a null event.  In either case, the where
  628. ** field of the event record will contain the current position of the mouse in
  629. ** global coordinates and the modifiers field will reflect the current state of
  630. ** the modifiers.  Another way to get the global coordinates is to call
  631. ** GetMouse and LocalToGlobal, but that requires being sure that thePort is set
  632. ** to a valid port. */
  633.  
  634. #pragma segment UtilMain
  635. Point    GetGlobalMouse(void)
  636. {
  637.     EventRecord    event;
  638.     
  639.     OSEventAvail(kNoEvents, &event);    /* we aren’t interested in any events */
  640.     return(event.where);                /* just the mouse position */
  641. }
  642.  
  643.  
  644.  
  645. /*****************************************************************************/
  646.  
  647.  
  648.  
  649. /* Given a window, this will return the top left point of the window’s port in
  650. ** global coordinates.  Something this doesn’t include is the window’s drag
  651. ** region (or title bar).  This returns the top left point of the window’s
  652. ** content area only. */
  653.   
  654. #pragma segment UtilMain
  655. Point    GetGlobalTopLeft(WindowPtr window)
  656. {
  657.     GrafPtr            oldPort;
  658.     Point            globalPt;
  659.     
  660.     GetPort(&oldPort);
  661.     SetPort(window);
  662.     globalPt = TopLeft(window->portRect);
  663.     LocalToGlobal(&globalPt);
  664.     SetPort(oldPort);
  665.     return(globalPt);
  666. }
  667.  
  668.  
  669.  
  670. /*****************************************************************************/
  671.  
  672.  
  673.  
  674. /* Return the amount of free space on the volume in KBytes. -1 is returned as
  675. ** the size if there is an error. */
  676.  
  677. #pragma segment UtilInit
  678. long    GetKFreeSpace(short vRefNum)
  679. {
  680.     HParamBlockRec    pb;
  681.     OSErr            err;
  682.  
  683.     pb.volumeParam.ioNamePtr = NULL;            /* we don't care about the name */
  684.     pb.volumeParam.ioVRefNum = vRefNum;
  685.     pb.volumeParam.ioVolIndex = 0;            /* use ioVRefNum only */
  686.     err = PBHGetVInfo(&pb, false);
  687.  
  688.     if (err == noErr)
  689.         return((pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz) / 1024);
  690.     else
  691.         return(-1);
  692. }
  693.  
  694.  
  695.  
  696. /*****************************************************************************/
  697.  
  698.  
  699.  
  700. #pragma segment UtilMain
  701. Rect    GetMainScreenRect(void)
  702. {
  703.     GDHandle    mainDevice;
  704.     GrafPtr        mainPort;
  705.  
  706.     if (gQDVersion > kQDOriginal) {
  707.         mainDevice = GetMainDevice();
  708.         return((*mainDevice)->gdRect);
  709.     } else {
  710.         GetWMgrPort(&mainPort);
  711.         return(mainPort->portRect);
  712.     }
  713. }
  714.  
  715.  
  716.  
  717. /*****************************************************************************/
  718.  
  719.  
  720.  
  721. /* Find the greatest overlap device for the given global rectangle. */
  722.  
  723. #pragma segment UtilInit
  724. GDHandle    GetRectDevice(Rect globalRect)
  725. {
  726.     long        area;
  727.     long        maxArea;
  728.     GDHandle    device;
  729.     GDHandle    deviceToReturn;
  730.     Rect        intersection;
  731.  
  732.     deviceToReturn = GetMainDevice();            /* Use as default choice. */
  733.     maxArea = 0;
  734.  
  735.     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  736.         if (TestDeviceAttribute(device, screenDevice)
  737.           && TestDeviceAttribute(device, screenActive)
  738.           && SectRect(&globalRect, &((*device)->gdRect), &intersection)) {
  739.             area = (intersection.right - intersection.left) *
  740.                    (intersection.bottom - intersection.top);
  741.             if (area > maxArea) {
  742.                 deviceToReturn = device;
  743.                 maxArea = area;
  744.             }
  745.         }
  746.     }
  747.     return(deviceToReturn);
  748. }
  749.  
  750.  
  751.  
  752. /*****************************************************************************/
  753.  
  754.  
  755.  
  756. /* Find the rect of the greatest overlap device for the given global rect. */
  757.  
  758. #pragma segment UtilInit
  759. Rect    GetRectDeviceRect(Rect globalRect)
  760. {
  761.     if (gQDVersion > kQDOriginal)
  762.         return((*GetRectDevice(globalRect))->gdRect);
  763.     else
  764.         return(GetMainScreenRect());
  765. }
  766.  
  767.  
  768.  
  769. /*****************************************************************************/
  770.  
  771.  
  772.  
  773. /* Given a window positioning procedure pointer, a window ID and a window
  774. ** pointer the window relates to, this function open a new window by either
  775. ** a NewCWindow or a NewWindow call, depending on the value of inColor.  The
  776. ** window will be opened invisible, independent of what the resource says.
  777. ** Once the window is opened successfully, the positioning procedure is
  778. ** called.  The positioning procedure is passed a pointer to the just-opened
  779. ** invisible window and a pointer to the related window.  It is up to the
  780. ** positioning procedure to move the invisible window to the correct location
  781. ** on the correct device.  Once the positioning procedure returns, the window
  782. ** will be made visible if so indicated by the resource. */
  783.  
  784. #pragma segment UtilMain
  785. WindowPtr    GetSomeKindOfWindow(PositionWndProcPtr whatKind, short windID,
  786.                                 Ptr storage, WindowPtr relatedWindow,
  787.                                 WindowPtr behind, Boolean inColor)
  788. {
  789.     WindowTHndl        windowResource;
  790.     WindowTemplate    wt;                /* Window template. */
  791.     WindowPtr        aWindow;
  792.     OSErr            err;
  793.  
  794.     if (!gQDVersion) inColor = false;
  795.  
  796.     aWindow = NULL;        /* Assume we will fail.  (Good attitude.) */
  797.  
  798.     if (!storage) storage = NewPtr(sizeof(WindowRecord));
  799.  
  800.     if (storage) {            /* If we have memory for the window record... */
  801.  
  802.         if (windowResource = (WindowTHndl)GetAppResource('WIND', windID, &err)) {
  803.             /* If we can load the window resource... */
  804.  
  805.             wt = **windowResource;        /* Make local copy of resource. */
  806.  
  807.             aWindow = (inColor ? NewCWindow(storage, &wt.boundsRect,
  808.                                             wt.title, false, wt.procID,
  809.                                             behind, wt.goAwayFlag, wt.refCon)
  810.                                : NewWindow(storage, &wt.boundsRect, wt.title,
  811.                                            false, wt.procID,
  812.                                            behind, wt.goAwayFlag, wt.refCon));
  813.                 /* Open either a regular or color window. */
  814.  
  815.             if (aWindow) {        /* If we were able to open a window... */
  816.                 (*whatKind)(aWindow, relatedWindow);
  817.                     /* Call the designated window positioning procedure. */
  818.  
  819.                 if (wt.visible) ShowWindow(aWindow);
  820.                     /* If resource says window should be visible, do it. */
  821.             }
  822.         }
  823.         if (!aWindow) DisposePtr(storage);
  824.             /* If we failed, then get rid of window record memory. */
  825.     }
  826.  
  827.     return(aWindow);
  828. }
  829.  
  830.  
  831.  
  832. /*****************************************************************************/
  833.  
  834.  
  835.  
  836. /* Given a window ID and a window pointer the window relates to, this function
  837. ** will stagger the window’s rectangle before showing it on the proper screen.
  838. ** This follows the Apple Human Interface Guidelines for where to place a
  839. ** staggered window on the screen.  If the window is not closely associated
  840. ** with another window, pass a NULL for the window pointer of the related
  841. ** window.  If you pass a NULL, the window is simply displayed where the
  842. ** resource would indicate. */
  843.  
  844. #pragma segment UtilMain
  845. WindowPtr    GetStaggeredWindow(short id, Ptr storage, WindowPtr relatedWindow,
  846.                                WindowPtr behind, Boolean inColor)
  847. {
  848.     return(GetSomeKindOfWindow(StaggerWindow, id, storage, relatedWindow, behind, inColor));
  849. }
  850.  
  851.  
  852.  
  853. /*****************************************************************************/
  854.  
  855.  
  856.  
  857. /*    Check the bits of a trap number to determine its type. */
  858.  
  859. #pragma segment UtilInit
  860. TrapType    GetTrapType(short theTrap)
  861. {
  862.     /* OS traps start with A0, Tool with A8 or AA. */
  863.     if ((theTrap & 0x0800) == 0)                    /* per D.A. */
  864.         return (OSTrap);
  865.     else
  866.         return (ToolTrap);
  867. }
  868.  
  869.  
  870.  
  871. /*****************************************************************************/
  872.  
  873.  
  874.  
  875. /* Given a window pointer, return the global rectangle that encloses the
  876. ** content area of the window. */
  877.  
  878. #pragma segment UtilMain
  879. Rect    GetWindowContentRect(WindowPtr window)
  880. {
  881.     WindowPtr    oldPort;
  882.     Rect        contentRect;
  883.  
  884.     GetPort(&oldPort);
  885.     SetPort(window);
  886.     contentRect = window->portRect;
  887.     LocalToGlobalRect(&contentRect);
  888.     SetPort(oldPort);
  889.     return(contentRect);
  890. }
  891.  
  892.  
  893.  
  894. /*****************************************************************************/
  895.  
  896.  
  897.  
  898. /* This procedure counts the number of windows in the application plane.
  899. ** You have the choices of also including DAs and invisible windows in
  900. ** this count. */
  901.  
  902. #pragma segment UtilMain
  903. short    GetWindowCount(Boolean includeDAs, Boolean includeInvisibles)
  904. {
  905.     WindowPeek    window;
  906.     short        count;
  907.  
  908.     for (count = 0, window = (WindowPeek)LMGetWindowList();
  909.          (window != NULL); window = window->nextWindow) {
  910.  
  911.         if ((window->windowKind < 0) && (!includeDAs)) continue;
  912.         if ((window->visible) || (includeInvisibles)) count++;
  913.     }
  914.     return (count);
  915. }
  916.  
  917.  
  918.  
  919. /*****************************************************************************/
  920.  
  921.  
  922.  
  923. /* Find the greatest overlap device for the given window. */
  924.  
  925. #pragma segment UtilInit
  926. GDHandle    GetWindowDevice(WindowPtr window)
  927. {
  928.     return(GetRectDevice(GetWindowStructureRect(window)));
  929. }
  930.  
  931.  
  932.  
  933. /*****************************************************************************/
  934.  
  935.  
  936.  
  937. /* Given a window pointer, find the device that contains most of the window
  938. ** and return the device's bounding rectangle. */
  939.  
  940. #pragma segment UtilMain
  941. Rect    GetWindowDeviceRect(WindowPtr window)
  942. {
  943.     if (gQDVersion > kQDOriginal)
  944.         return((*GetWindowDevice(window))->gdRect);
  945.     else
  946.         return(GetMainScreenRect());
  947. }
  948.  
  949.  
  950.  
  951. /*****************************************************************************/
  952.  
  953.  
  954.  
  955. /* Given a window pointer, find the device that contains most of the window
  956. ** and return the device's bounding rectangle.  If this device is the main
  957. ** device, then remove the menubar area from the rectangle. */
  958.  
  959. #pragma segment UtilMain
  960. Rect    GetWindowDeviceRectNMB(WindowPtr window)
  961. {
  962.     Rect        deviceRect, tempRect;
  963.  
  964.     deviceRect = GetWindowDeviceRect(window);
  965.     tempRect = GetMainScreenRect();
  966.     if (EqualRect(&deviceRect, &tempRect)) deviceRect.top += GetMBarHeight();
  967.  
  968.     return(deviceRect);
  969. }
  970.  
  971.  
  972.  
  973. /*****************************************************************************/
  974.  
  975.  
  976.  
  977. /* This procedure is used to get the rectangle that surrounds the entire
  978. ** structure of a window.  This is true whether or not the window is visible.
  979. ** If the window is visible, then it is a simple matter of using the bounding
  980. ** rectangle of the structure region.  If the window is invisible, then the
  981. ** strucRgn is not correct.  To make it correct, then window has to be moved
  982. ** way off the screen and then made visible.  This generates a valid strucRgn,
  983. ** although it is valid for the position that is way off the screen.  It still
  984. ** needs to be offset back into the original position.  Once the bounding
  985. ** rectangle for the strucRgn is obtained, the window can then be hidden again
  986. ** and moved back to its correct location.  Note that ShowHide is used,
  987. ** instead of ShowWindow and HideWindow.  HideWindow can change the plane of
  988. ** the window.  Also, ShowHide does not affect the hiliting of windows. */
  989.  
  990. #pragma segment UtilMain
  991. Rect    GetWindowStructureRect(WindowPtr window)
  992. {
  993. #define kOffscreenLoc 0x4000
  994.  
  995.     GrafPtr        oldPort;
  996.     Rect        structureRect;
  997.     Point        windowLoc;
  998.     
  999.     if (((WindowPeek)window)->visible)
  1000.         structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1001.  
  1002.     else {
  1003.         GetPort(&oldPort);
  1004.         SetPort(window);
  1005.         windowLoc = GetGlobalTopLeft(window);
  1006.         MoveWindow(window, windowLoc.h, kOffscreenLoc, false);
  1007.         ShowHide(window, true);
  1008.         structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1009.         ShowHide(window, false);
  1010.         MoveWindow(window, windowLoc.h, windowLoc.v, false);
  1011.         SetPort(oldPort);
  1012.         OffsetRect(&structureRect, 0, windowLoc.v - kOffscreenLoc);
  1013.     }
  1014.     return(structureRect);
  1015. }
  1016.  
  1017.  
  1018.  
  1019. /*****************************************************************************/
  1020.  
  1021.  
  1022.  
  1023. #pragma segment UtilMain
  1024. void    GlobalToLocalRect(Rect *aRect)
  1025. {
  1026.     GlobalToLocal(&TopLeft(*aRect));
  1027.     GlobalToLocal(&BotRight(*aRect));
  1028. }
  1029.  
  1030.  
  1031.  
  1032. /*****************************************************************************/
  1033.  
  1034.  
  1035.  
  1036. #pragma segment UtilInit
  1037. void    InitToolBox(void)
  1038. {
  1039.     InitGraf((Ptr) &QD(thePort));
  1040.     InitFonts();
  1041.     InitWindows();
  1042.     InitMenus();
  1043.     TEInit();
  1044.     InitDialogs(NULL);
  1045.     InitCursor();
  1046. }
  1047.     
  1048.  
  1049.  
  1050. /*****************************************************************************/
  1051.  
  1052.  
  1053.  
  1054. /* InitUtilities sets up some global variables for use by the utilities
  1055. ** package.  If you call StandardInitialization, you don't need to call this,
  1056. ** as it will do it for you. */ 
  1057.  
  1058. #pragma segment UtilInit
  1059. void    InitUtilities(void)
  1060. {
  1061.     //Handle    apParam;
  1062.     Handle    bndlResource;
  1063.     OSErr    err;
  1064.  
  1065.     gUtilitiesInited = false;
  1066.  
  1067.     /* Init all the Gestalt variables */
  1068.     gMachineType = GetGestaltResult (gestaltMachineType);
  1069.     gSystemVersion = GetGestaltResult (gestaltSystemVersion);
  1070.     gProcessorType = GetGestaltResult (gestaltProcessorType);
  1071.  
  1072.     /* We only concern ourselves with there being an FPU, not which type it is */
  1073.     gHasFPU = (GetGestaltResult (gestaltFPUType) != gestaltNoFPU);
  1074.     
  1075.     /*
  1076.      *    We only concern ourselves with the major QD version number
  1077.      *    0 for original QD, 1 for 8-bit color QD, and 2 for 32-bit QD
  1078.      */
  1079.     gQDVersion = (GetGestaltResult (gestaltQuickdrawVersion) >> 8) & 0xFF;
  1080.     gKeyboardType = GetGestaltResult (gestaltKeyboardType);
  1081.     gAppleTalkVersion = GetGestaltResult (gestaltAppleTalkVersion);
  1082.     
  1083.     /* We only concern ourselves with there being an PMMU, not which type it is */
  1084.     gHasPMMU = GetGestaltResult (gestaltMMUType) >= gestalt68851;
  1085.     gAUXVersion = GetAUXVersion ();
  1086.  
  1087.     gHasWaitNextEvent = TrapExists(_WaitNextEvent);
  1088.     gInBackground = false;
  1089.     
  1090. /* 
  1091. 10/16/90 pvh/MacDTS
  1092. With GetAppParams(), THINK C in project mode returns the project resource file AND NOT 
  1093. the .rsrc file, which is what one really wants (trust me).  If THINK is present we will 
  1094. return CurResFile() which will be the .rsrc file instead.  The name will still be the 
  1095. project name in project mode, so be aware of that.
  1096. */
  1097.     //GetAppParms(gAppName, &gAppResRef, &apParam);
  1098.     gAppResRef = CurResFile();            /* returns refNum of .rsrc file */
  1099.     bndlResource = GetAppIndResource('BNDL', 1, &err);
  1100.     if (bndlResource)
  1101.         gSignature = *(OSType *) (*bndlResource);
  1102.  
  1103.     gUtilitiesInited = true;
  1104. }
  1105.  
  1106.  
  1107.  
  1108. /*****************************************************************************/
  1109.  
  1110.  
  1111.  
  1112. /* Check to see if a window belongs to the application.  If the window pointer
  1113. ** passed was NULL, then it could not be an application window.  WindowKinds
  1114. ** that are negative belong to the system and windowKinds less than userKind
  1115. ** are reserved by Apple except for windowKinds equal to dialogKind, which
  1116. ** mean it is a dialog. */  
  1117.  
  1118. #pragma segment UtilMain
  1119. Boolean    IsAppWindow(WindowPtr window)
  1120. {
  1121.     if (window)
  1122.         return (((WindowPeek)window)->windowKind >= userKind);
  1123.     else 
  1124.         return false;
  1125.  
  1126. }
  1127.  
  1128.  
  1129.  
  1130. /*****************************************************************************/
  1131.  
  1132.  
  1133.  
  1134. /* Check to see if a window belongs to a desk accessory. */
  1135.  
  1136. #pragma segment UtilMain
  1137. Boolean    IsDAWindow(WindowPtr window)
  1138. {
  1139.     if (window)    /* DA windows have negative windowKinds */
  1140.         return (((WindowPeek) window)->windowKind < 0);
  1141.     else
  1142.         return false;
  1143. }
  1144.  
  1145.  
  1146.  
  1147. /*****************************************************************************/
  1148.  
  1149.  
  1150.  
  1151. #pragma segment UtilMain
  1152. void    LocalToGlobalRect(Rect *aRect)
  1153. {
  1154.     LocalToGlobal(&TopLeft(*aRect));
  1155.     LocalToGlobal(&BotRight(*aRect));
  1156. }
  1157.  
  1158.  
  1159.  
  1160. /*****************************************************************************/
  1161.  
  1162.  
  1163.  
  1164. #pragma segment UtilMain
  1165. char    LockHandleHigh(Handle theHandle)
  1166. {
  1167.     char    hstate;
  1168.  
  1169.     hstate = HGetState(theHandle);
  1170.     MoveHHi(theHandle);
  1171.     HLock(theHandle);
  1172.     return(hstate);
  1173. }
  1174.  
  1175.  
  1176.  
  1177. /*****************************************************************************/
  1178.  
  1179.  
  1180.  
  1181. /* InitGraf is always implemented (trap $A86E).  If the trap table is big
  1182. ** enough, trap $AA6E will always point to either Unimplemented or some other
  1183. ** trap, but will never be the same as InitGraf.  Thus, you can check the size
  1184. ** of the trap table by asking if the address of trap $A86E is the same as
  1185. ** $AA6E. */
  1186.  
  1187. #pragma segment UtilInit
  1188. short    NumToolboxTraps(void)
  1189. {
  1190.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1191.         return (0x200);
  1192.     else
  1193.         return (0x400);
  1194. }
  1195.  
  1196.  
  1197.  
  1198. /*****************************************************************************/
  1199.  
  1200.  
  1201.  
  1202. /* Given any control handle, this will draw an outline around it.  This is used
  1203. ** for the default button of a window.  The extra nice feature here is that
  1204. ** I’ll erase the outline for buttons that are inactive.  Seems like there
  1205. ** should be a Toolbox call for getting a control’s hilite state.  Since there
  1206. ** isn’t, I have to look into the control record myself.  This should be called
  1207. ** for update and activate events.
  1208. **
  1209. ** The method for determining the oval diameters for the roundrect is a little
  1210. ** different than that recommended by Inside Mac. IM I-407 suggests that you
  1211. ** use a hardcoded (16,16) for the diameters.  However, this only looks good
  1212. ** for small roundrects.  For larger ones, the outline doesn’t follow the inner
  1213. ** roundrect because the CDEF for simple buttons doesn’t use (16,16).  Instead,
  1214. ** it uses half the height of the button as the diameter.  By using this
  1215. ** formula, too, our outlines look better.
  1216. **
  1217. ** WARNING: This will set the current port to the control’s window. */
  1218.  
  1219. #pragma segment UtilMain
  1220. void    OutlineControl(ControlHandle button)
  1221. {
  1222.     Rect        theRect;
  1223.     PenState    curPen;
  1224.     short        buttonOval;
  1225.  
  1226.     if (button) {
  1227.         SetPort((*button)->contrlOwner);
  1228.         GetPenState(&curPen);
  1229.         PenNormal();
  1230.         theRect = (*button)->contrlRect;
  1231.         InsetRect(&theRect, kButtonFrameInset, kButtonFrameInset);
  1232.         buttonOval = (theRect.bottom - theRect.top) / 2 + 2;
  1233.  
  1234.         PenPat((*button)->contrlHilite == kCntlActivate ? &QD(black) : &QD(gray));
  1235.  
  1236.         PenSize(kButtonFrameSize, kButtonFrameSize);
  1237.         FrameRoundRect(&theRect, buttonOval, buttonOval);
  1238.         SetPenState(&curPen);
  1239.     }
  1240. }
  1241.  
  1242.  
  1243.  
  1244. /*****************************************************************************/
  1245.  
  1246.  
  1247.  
  1248. #pragma segment UtilMain
  1249. void    OutlineDialogItem(DialogPtr dlgPtr, short item)
  1250. {
  1251.     short iKind;
  1252.     Handle iHandle;
  1253.     Rect iRect;
  1254.  
  1255.     GetDialogItem (dlgPtr, item, &iKind, &iHandle, &iRect);
  1256.     OutlineControl((ControlHandle) iHandle);
  1257. }
  1258.  
  1259.  
  1260.  
  1261. /*****************************************************************************/
  1262.  
  1263.  
  1264.  
  1265. /* Given two rectangles, this function positions the second within the first
  1266. ** one so that it maintains the spacing specified by the horzRatio and
  1267. ** vertRatio parameters.  In other words, to center an inner rectangle
  1268. ** hoizontally, but have its center be 1/3 from the top of the outer rectangle,
  1269. ** call this function with horzRatio = FixRatio (1, 2), vertRatio =
  1270. ** FixRatio(1, 3).  We use Fixed rather than floating point to avoid
  1271. ** complications when mixing MC68881/non-MC68881 versions of Utilities. */
  1272.  
  1273. #pragma segment UtilMain
  1274. void    PositionRectInRect(Rect outerRect, Rect *innerRect, Fixed horzRatio, Fixed vertRatio)
  1275. {
  1276.     short        outerRectHeight;
  1277.     short        outerRectWidth;
  1278.     short        innerRectHeight;
  1279.     short        innerRectWidth;
  1280.     short        yLocation;
  1281.     short        xLocation;
  1282.  
  1283.     outerRectHeight = outerRect.bottom - outerRect.top;
  1284.     outerRectWidth = outerRect.right - outerRect.left;
  1285.  
  1286.     innerRectHeight = innerRect->bottom - innerRect->top;
  1287.     innerRectWidth = innerRect->right - innerRect->left;
  1288.         yLocation = Fix2Long(FixMul(Long2Fix(outerRectHeight - innerRectHeight), vertRatio))
  1289.             + outerRect.top;
  1290.         xLocation = Fix2Long(FixMul(Long2Fix(outerRectWidth - innerRectWidth), horzRatio))
  1291.             + outerRect.left;
  1292.  
  1293.     innerRect->top = yLocation;
  1294.     innerRect->left = xLocation;
  1295.     innerRect->bottom = yLocation + innerRectHeight;
  1296.     innerRect->right = xLocation + innerRectWidth;
  1297. }
  1298.  
  1299.  
  1300.  
  1301. /*****************************************************************************/
  1302.  
  1303.  
  1304.  
  1305. /* Concatenate a Pascal string onto another. */
  1306.  
  1307. #pragma segment UtilMain
  1308. void    PStrConcat(Str255 targetStr, Str255 appendStr)
  1309. {
  1310.     long appendLen;
  1311.  
  1312.     /* Figure out number of bytes to copy, up to 255 */
  1313.     if ((StrLength (targetStr) + StrLength (appendStr)) > 255)
  1314.         appendLen = 255 - StrLength (targetStr);
  1315.     else
  1316.         appendLen = StrLength (appendStr);
  1317.  
  1318.     if (appendLen > 0) {
  1319.         BlockMove (appendStr + 1, targetStr + StrLength (targetStr) + 1, appendLen);
  1320.         targetStr [0] += appendLen;
  1321.     }
  1322. }
  1323.  
  1324.  
  1325.  
  1326. /*****************************************************************************/
  1327.  
  1328.  
  1329.  
  1330. #pragma segment UtilInit
  1331. void    PullApplicationToFront(void)
  1332. {
  1333. #define kBroughtToFront 3
  1334.  
  1335.     EventRecord event;
  1336.     short        count;
  1337.  
  1338.     for (count = 1; count <= kBroughtToFront; count++)
  1339.         EventAvail(everyEvent, &event);
  1340. }
  1341.  
  1342.  
  1343.  
  1344. /*****************************************************************************/
  1345.  
  1346.  
  1347.  
  1348. /* Given the button control handle, this will cause the button to look as if it
  1349. ** has been clicked in.  This is nice to do for the user if they type return or
  1350. ** enter to select the default item. */
  1351.  
  1352. #pragma segment UtilMain
  1353. void    SelectButton(ControlHandle button)
  1354. {
  1355.     unsigned long            finalTicks;
  1356.     
  1357.     HiliteControl(button, kSelect);
  1358.     Delay(kDelayTime, &finalTicks);
  1359.     HiliteControl(button, kDeselect);
  1360. }
  1361.  
  1362.  
  1363.  
  1364. /*****************************************************************************/
  1365.  
  1366.  
  1367.  
  1368. /* Handy function for setting the value of a radio button.  Given a dialog
  1369. ** pointer, and item number, and a state, this function will take care of the
  1370. ** rest. */
  1371.  
  1372. #pragma segment UtilMain
  1373. void    SetCheckOrRadioButton(DialogPtr dlgPtr, short itemNo, short state)
  1374. {
  1375.     short    iKind;
  1376.     Handle    iHandle;
  1377.     Rect    iRect;
  1378.  
  1379.     GetDialogItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  1380.     SetControlValue((ControlHandle) iHandle, state);
  1381. }
  1382.  
  1383.  
  1384.  
  1385. /*****************************************************************************/
  1386.  
  1387.  
  1388.  
  1389. /* This algorithm for staggering windows does quite a good job.  It also is
  1390. ** quite gnarly.  Here's the deal:
  1391. ** There are pre-designated positions that we will try when positioning a
  1392. ** window.  These slots will be tried from the upper-left corner towards the
  1393. ** lower-right corner.  If there are other windows in that slot, then we will
  1394. ** consider that slot taken, and proceed to the next slot.  A slot is
  1395. ** determined to be taken by checking a point with a slop area.  This slop
  1396. ** area is diamond-shaped, not simply rectangular.  If there is no other
  1397. ** visible window with an upper-left corner within the slopt diamond, then
  1398. ** we are allowed to position our window there.
  1399. ** The above rule holds true unless this forces the window to be partly
  1400. ** off the screen.  If the window ends up partly off the screen, then we try
  1401. ** a new diagonal just below the first diagonal we tried.  We keep trying
  1402. ** lower and lower diagonals until we find a spot for the window, or the
  1403. ** diagonal doesn't fit on the screen at all.  If the diagonal doesn't fit,
  1404. ** then we try diagonals to the right of the first diagonal.  If even this
  1405. ** doesn't work, then we give up and put the window in the original spot
  1406. ** we tried. */
  1407.  
  1408. #pragma segment UtilMain
  1409. Rect    StaggerWindow(WindowPtr window, WindowPtr relatedWindow)
  1410. {
  1411.     WindowPtr    whichDevice, staggerFromWindow;
  1412.     Rect        deviceRect, oldWindowRect, newWindowRect, slot1;
  1413.     Rect        testRect, contentRect, staggerFromRect;
  1414.     Point        delta, absdelta;
  1415.     Boolean        contained, vertTry;
  1416.     short        diamondSize, diagNum, tryNum;
  1417.  
  1418.     if (!(whichDevice = relatedWindow)) whichDevice = window;
  1419.         /* If we have a window to stagger from, use the device for that window,
  1420.         ** else use the device for the window that is getting staggered. */
  1421.  
  1422.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  1423.         /* We now have the rect of the device we want to stagger within. */
  1424.  
  1425.     oldWindowRect = GetWindowStructureRect(window);
  1426.     newWindowRect.top    = deviceRect.top  + kStartPtV;
  1427.     newWindowRect.left   = deviceRect.left + kStartPtH;
  1428.     newWindowRect.bottom = newWindowRect.top  + oldWindowRect.bottom - oldWindowRect.top;
  1429.     newWindowRect.right  = newWindowRect.left + oldWindowRect.right  - oldWindowRect.left;
  1430.         /* We now have a new rect for the first window position slot. */
  1431.  
  1432.     slot1 = newWindowRect;
  1433.         /* We keep this slot in case we find no acceptable slots.  If we
  1434.         ** don't find an acceptable one, we will use this one anyway. */
  1435.  
  1436.     diamondSize = (kStaggerH < kStaggerV) ? kStaggerH : kStaggerV;
  1437.     for (diagNum = 0, vertTry = true;;) {
  1438.         for (tryNum = 0;; ++tryNum) {
  1439.  
  1440.             SectRect(&newWindowRect, &deviceRect, &testRect);
  1441.             if (!(contained = EqualRect(&newWindowRect, &testRect))) break;
  1442.                 /* Break if the slot we are testing went off the device. */
  1443.  
  1444.             for (staggerFromWindow = FrontWindow();
  1445.                  staggerFromWindow;
  1446.                  staggerFromWindow =
  1447.                     (WindowPtr)((WindowPeek)staggerFromWindow)->nextWindow
  1448.             ) {
  1449.                 if (!((WindowPeek)staggerFromWindow)->visible) continue;
  1450.                     /* This window is invisible.  Staggering from an invisible
  1451.                     ** window is going to confuse the user, so don't do it. */
  1452.  
  1453.                 testRect = GetWindowDeviceRectNMB(staggerFromWindow);
  1454.                 if (!EqualRect(&testRect, &deviceRect)) continue;
  1455.                     /* This window doesn't belong to the device we are trying to
  1456.                     ** stagger on, so skip it and go to the next window. */
  1457.  
  1458.                 staggerFromRect = GetWindowStructureRect(staggerFromWindow);
  1459.                 delta.v = staggerFromRect.top  - newWindowRect.top;
  1460.                 delta.h = staggerFromRect.left - newWindowRect.left;
  1461.                 if ((absdelta.v = delta.v) < 0) absdelta.v = -delta.v;
  1462.                 if ((absdelta.h = delta.h) < 0) absdelta.h = -delta.h;
  1463.                 if ((absdelta.h + absdelta.v) < diamondSize) {
  1464.                     if ((delta.h + delta.v) > 0)
  1465.                         OffsetRect(&newWindowRect, delta.h, delta.v);
  1466.                             /* If the window that took our slot is closer to
  1467.                             ** the lower-right corner than we are, then use
  1468.                             ** this window's location as the basis for the
  1469.                             ** slots from now on.  This will align new windows
  1470.                             ** with previous windows that are not gridded to
  1471.                             ** the default slot positions.  The check for > 0
  1472.                             ** is necessary to prevent bouncing between two
  1473.                             ** existing windows.  This check guarantees that
  1474.                             ** we are progressing with the evaluation. */
  1475.                     break;
  1476.                         /* Break because this slot is already used. */    
  1477.                 }
  1478.             }
  1479.  
  1480.             if (!staggerFromWindow) break;
  1481.                 /* If the window pointer is NULL, then we tried all the windows
  1482.                 ** and none of them occupied this slot.  This means that the
  1483.                 ** slot is available for the new window. */
  1484.  
  1485.                 OffsetRect(&newWindowRect, kStaggerH, kStaggerV);
  1486.                 /* Since this slot was taken, try the next slot and go through
  1487.                 ** the window list again. */
  1488.         }
  1489.  
  1490.         if (contained) break;
  1491.         newWindowRect = slot1;
  1492.         if (!tryNum) {
  1493.             if (!vertTry) break;        /* Nothing works.  No spots at all. */
  1494.             vertTry = false;            /* Try across for the next pass. */
  1495.             diagNum = 0;
  1496.         }
  1497.         ++diagNum;
  1498.         if (vertTry) OffsetRect(&newWindowRect, 0, diagNum * kStaggerV);
  1499.         else         OffsetRect(&newWindowRect, diagNum * kStaggerH, 0);
  1500.     }
  1501.  
  1502.     contentRect = GetWindowContentRect(window);
  1503.         /* Get where the window is now. */
  1504.  
  1505.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  1506.                             newWindowRect.top  - oldWindowRect.top);
  1507.         /* Calculate the new content rect. */
  1508.  
  1509.     MoveWindow(window, contentRect.left, contentRect.top, false);
  1510.         /* Move the window to the new location. */
  1511.  
  1512.     return(contentRect);
  1513. }
  1514.  
  1515.  
  1516.  
  1517. /*****************************************************************************/
  1518.  
  1519.  
  1520.  
  1521. #pragma segment UtilMain
  1522. void    StandardAbout(short appNameStringID)
  1523. {
  1524.     StringHandle    apNameHndl;
  1525.     VersRecHndl        curVersion;
  1526.     Str255            apName;
  1527.     Str255            verNum = "\p????";
  1528.     Ptr                verNumLocation;
  1529.     OSErr            err;
  1530.  
  1531.     if (!gUtilitiesInited)                /* Make sure we were initialized */
  1532.         InitUtilities();
  1533.         
  1534.     apNameHndl = (StringHandle)NULL;
  1535.     if (appNameStringID != kUseRealAppName) {
  1536.         if (appNameStringID != kUseCreatorString)
  1537.             apNameHndl = GetString(appNameStringID);
  1538.         if (!apNameHndl)
  1539.             apNameHndl = (StringHandle) GetAppResource(gSignature, 0, &err);
  1540.     }
  1541.  
  1542.     if ((!apNameHndl) || (appNameStringID == kUseRealAppName))
  1543.         PStrCopy(apName, gAppName);
  1544.     else
  1545.         PStrCopy(apName, *apNameHndl);
  1546.  
  1547.     curVersion = (VersRecHndl) GetAppResource('vers', 1, &err);
  1548.     if (curVersion) {
  1549.         verNumLocation = (Ptr) ((long)(*curVersion)->shortVersion
  1550.                         + (long)*(*curVersion)->shortVersion + 1);
  1551.         PStrCopy(verNum, verNumLocation);
  1552.     }
  1553.  
  1554.     ParamText(apName, verNum, "\p", "\p");
  1555.  
  1556.     CenteredAlert(rStdAboutAlert, NULL);
  1557. }
  1558.  
  1559.  
  1560.  
  1561. /*****************************************************************************/
  1562.  
  1563.  
  1564.  
  1565. #pragma segment UtilInit
  1566. void    StandardInitialization(short callsToMoreMasters)
  1567. {
  1568.     InitToolBox();
  1569.  
  1570.     while (callsToMoreMasters--)
  1571.         MoreMasters();
  1572.     
  1573.     PullApplicationToFront();
  1574.     
  1575.     InitUtilities();
  1576. }
  1577.  
  1578.  
  1579.  
  1580. /*****************************************************************************/
  1581.  
  1582.  
  1583.  
  1584. #pragma segment UtilInit
  1585. void    StandardMenuSetup(short MBARID, short AppleMenuID)
  1586. {
  1587.     Handle menuBar = GetNewMBar(MBARID);            /* read menus into menu bar */
  1588.     if (!menuBar) 
  1589.         DeathAlert(rUtilStrings, eNoMenuBar);
  1590.     SetMenuBar(menuBar);                            /* install menus */
  1591.     DisposeHandle(menuBar);
  1592.     AppendResMenu(GetMenuHandle(AppleMenuID), 'DRVR');    /* add DA names to Apple menu */
  1593.     DrawMenuBar();
  1594. }
  1595.  
  1596.  
  1597.  
  1598. /*****************************************************************************/
  1599.  
  1600.  
  1601.  
  1602. #pragma segment UtilMain
  1603. void    ToggleCheck(DialogPtr dlgPtr, short chkItem)
  1604. {
  1605.     short iKind;
  1606.     Handle iHandle;
  1607.     Rect iRect;
  1608.  
  1609.     GetDialogItem (dlgPtr, chkItem, &iKind, &iHandle, &iRect);
  1610.     SetControlValue((ControlHandle) iHandle, !GetControlValue((ControlHandle)iHandle));
  1611. }
  1612.  
  1613.  
  1614.  
  1615. /*****************************************************************************/
  1616.  
  1617.  
  1618.  
  1619. /* Check to see if a given trap is implemented.  This is only used by the
  1620. ** Initialize function in this program, so we put it in the
  1621. ** Initialize segment. */ 
  1622.  
  1623. #pragma segment UtilInit
  1624. Boolean TrapExists(short theTrap)
  1625. {
  1626.     TrapType    theTrapType;
  1627.  
  1628.     theTrapType = GetTrapType(theTrap);
  1629.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  1630.         theTrap = _Unimplemented;
  1631.  
  1632.     return (NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap,
  1633.                   theTrapType));
  1634. }
  1635.  
  1636.  
  1637.  
  1638. /*****************************************************************************/
  1639.  
  1640.  
  1641.  
  1642. /* Zoom the window to the size appropriate for the device that contains the
  1643. ** most of the window.  An additional feature is that you can state the
  1644. ** maximum that a window should be zoomed, either horizontally or vertically.
  1645. ** If you pass in a maximum of 0 for the zoom for either direction, then that
  1646. ** direction will be zoomed to fit the device. */
  1647.  
  1648. #pragma segment UtilMain
  1649. void    ZoomToWindowDevice(WindowPtr window, short maxWidth, short maxHeight,
  1650.                            short zoomDir, Boolean front)
  1651. {
  1652.      GrafPtr        oldPort;
  1653.     Rect        contentRect, structureRect, deviceRect, newRect;
  1654.     short        width, height, dx, dy;
  1655.  
  1656.     GetPort(&oldPort);
  1657.     SetPort(window);
  1658.     EraseRect(&window->portRect);         /* Recommended for cosmetic reasons. */
  1659.  
  1660.     /* If there is the possibility of multiple gDevices, then we must check them to
  1661.     ** make sure we are zooming onto the right display device when zooming out. */
  1662.  
  1663.     if ((zoomDir == inZoomOut) && (gQDVersion > kQDOriginal)) {
  1664.  
  1665.         contentRect      = GetWindowContentRect(window);
  1666.         structureRect = GetWindowStructureRect(window);
  1667.         deviceRect      = GetWindowDeviceRectNMB(window);
  1668.  
  1669.         deviceRect.left   += (contentRect.left - structureRect.left + 2);
  1670.         deviceRect.top    += (contentRect.top - structureRect.top + 2);
  1671.         deviceRect.right  -= (structureRect.right - contentRect.right + 2);
  1672.         deviceRect.bottom -= (structureRect.bottom - contentRect.bottom + 2);
  1673.         newRect = deviceRect;
  1674.  
  1675.         if (maxWidth)
  1676.             if ((width = deviceRect.right - deviceRect.left) > maxWidth)
  1677.                 newRect.right = (newRect.left = contentRect.left) + maxWidth;
  1678.         if (maxHeight)
  1679.             if ((height = deviceRect.bottom - deviceRect.top) > maxHeight)
  1680.                 newRect.bottom = (newRect.top = contentRect.top) + maxHeight;
  1681.         if ((dx = deviceRect.left - newRect.left) < 0)
  1682.             if ((dx = deviceRect.right - newRect.right) > 0)
  1683.                 dx = 0;
  1684.         if ((dy = deviceRect.top - newRect.top) < 0)
  1685.             if ((dy = deviceRect.bottom - newRect.bottom) > 0)
  1686.                 dy = 0;
  1687.         OffsetRect(&newRect, dx, dy);
  1688.  
  1689.         (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->stdState = newRect;
  1690.             /* Set up the WStateData record for this window. */
  1691.     }
  1692.  
  1693.     ZoomWindow(window, zoomDir, front);
  1694.     SetPort(oldPort);
  1695. }
  1696.  
  1697.  
  1698.  
  1699.